package com.youpingou.service.impl;

import com.alibaba.fastjson.JSON;
import com.youpingou.domain.Cart;
import com.youpingou.service.CartService;
import com.youpingou.util.JWTUtil;
import io.jsonwebtoken.Claims;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.List;

/**
 * @auther Created by yuanxinqi
 */
@Service
public class CartServiceImpl implements CartService {

    @Autowired
    private RedisTemplate<String,String> redisTemplate;


    /**
     *
     * @param cartRequest 当前购物车商品数据
     * @param request 请求
     */
    public void addToCart(Cart cartRequest, HttpServletRequest request){
        //1. 获取token
        String token = request.getHeader("authorization");
        System.out.println(token);
        //2. 解析token
        Claims claims = JWTUtil.parseToken(token, "admin");
        String userId = claims.get("userId").toString();

        //4. 根据userId去购物车中取出数据
        String info = redisTemplate.opsForValue().get(userId);
        //5. 判断info是否有值
        if(info!=null&& StringUtils.isNotBlank(info)){
            //6. 解析info
            List<Cart> carts = JSON.parseArray(info, Cart.class);
            //7. 遍历当前购物车集合，判断商品是否已经存在
            Cart cart = null;
            for(Cart c:carts){
                if(c.getSkuid().equals(cartRequest.getSkuid())){
                    cart = c;
                    break;
                }
            }

            if(cart!=null){
                //8. 如果存在，改变数量
                // 取出cart对象修改，由于是对象，是引用数据类型，在外面改了，List集合中的数据也会自动改变
                cart.setCount(cart.getCount()+cartRequest.getCount());
            }else{
                //9. 如果不存在，则追加
                carts.add(cartRequest);
            }
            // 存入redis
            redisTemplate.opsForValue().set(userId,JSON.toJSONString(carts));

        }else{
            //info没有值
            ArrayList<Cart> list = new ArrayList<>();
            list.add(cartRequest);
            // 存入redis
            redisTemplate.opsForValue().set(userId,JSON.toJSONString(list));
        }
    }

    /**
     * 登录合并购物车
     * 1 根据用户id查找购物车信息
     * 2 判断购物车是否存在
     * 3 如果不存在，直接将当前的购物车信息添加进redis
     * 4 如果存在，判断是新增数量，还是将商品加入购物车？
     *   4.1 新增数量：购物车中已经存该商品
     *   4.2 将商品加入购物车：购物车中还没有这个商品
     */
    public void addLoginCart(Integer userid, String cart) {
        //1 根据用户id查找购物车信息
        String redisInfo = redisTemplate.opsForValue().get(userid.toString());
        //2 判断redisInfo中是否有数据
        if(redisInfo==null||"".equals(redisInfo.trim())){
            //redis中没有数据
            redisTemplate.opsForValue().set(userid.toString(),cart);
            return;
        }
        //3 如果能够执行到此处，表明当前用户的购物车中是有数据的
        //3.1 将页面购物车和后台购物车都转成对象，然后进行判断
        List<Cart> clientCarts = JSON.parseArray(cart, Cart.class);
        List<Cart> redisCarts = JSON.parseArray(redisInfo, Cart.class);

        //4 将clientCarts的数据合并到redisCarts中
        //使用嵌套for循环，遍历客户端的ClientCarts中的数据，一条一条的去redisCarts中查找，判断是新增数量还是添加商品？
        for(Cart clientCart:clientCarts){
            //遍历redisCarts
            //拿clientCart的数据去redisCarts中对比
            Cart rc = null;//当skuid相等的时候，记录到rc中
            for(Cart redisCart:redisCarts){
                if(clientCart.getSkuid().equals(redisCart.getSkuid())){
                    rc = redisCart;
                    break;
                }
            }
            //判断rc是否为空，如果为空，直接添加商品，如果不为空，新增数量
            if(rc==null){
                redisCarts.add(clientCart);
            }else{
                rc.setCount(rc.getCount()+clientCart.getCount());
            }

        }
        //5 如果执行到此处，合并成功了，合并成功，将数据放入redis
        redisTemplate.opsForValue().set(userid.toString(),JSON.toJSONString(redisCarts));
    }

    @Override
    public List<Cart> findCartByToken(HttpServletRequest request) {
        /**
         * 实现业务逻辑
         * 1 获取token，解析token，最终目的拿到userid
         * 2 根据userid去redis中取出购物车数据
         * 3 封装返回结果
         */
        //1 获取token，解析token，最终拿到userid
        String token = request.getHeader("authorization");
        Claims claims = JWTUtil.parseToken(token, "admin");
        //2 解析是否成功
        if (claims==null){
            return null;
        }

        //3 如果代码可以执行到此行，表明token解析成功
        //获取用户的id
        String userId = claims.get("userId").toString();
        // 4 去redis中取数据
        String info = redisTemplate.opsForValue().get(userId);
        // 5 判断是否取到了info
        // 如果没有取到，返回null
        // 如果取到了，转成List<Cart>
        if(info!=null&&!"".equals(info.trim())){
            //转换
            List<Cart> list = JSON.parseArray(info, Cart.class);
            return list;
        }
        return null;

    }

    /**
     * 实现业务逻辑
     * 1 获取token
     * 2 解析token，获取userid
     * 3 根据userid获取购物车数据
     * 4 根据skuid找到购物车中的sku信息
     * 5 修改信息
     * 6 重新放入redis
     * @param skuid
     * @param cartReq
     * @param request
     * @return
     */
    public void updateCart(Integer skuid, Cart cartReq, HttpServletRequest request) {
        //1 获取token，并解析token，拿到userid
        String token = request.getHeader("authorization");
        Claims claims = JWTUtil.parseToken(token, "admin");
        //2 解析是否成功
        if (claims==null){
            return;
        }

        //3 如果代码可以执行到此行，表明token解析成功
        //获取用户的id
        String userId = claims.get("userId").toString();
        // 4 去redis中取数据
        String info = redisTemplate.opsForValue().get(userId);
        if(info!=null&&!"".equals(info.trim())){
            //购物车数据不为空
            //5 解析info
            List<Cart> list = JSON.parseArray(info, Cart.class);
            for (Cart c:list){
                if(c.getSkuid().equals(skuid)){
                    c.setCount(cartReq.getCount());
                    c.setChecked(cartReq.getChecked());
                    break;
                }
            }

            //将数据重新放入redis
            redisTemplate.opsForValue().set(userId,JSON.toJSONString(list));
        }
    }

    /**
     * 删除购物车商品的业务逻辑
     * 1 获取token，解析token，拿到userid
     * 2 根据userid获取购物车商品信息
     * 3 删除商品
     * @param skuid
     * @param request
     */
    public void deleteCart(Integer skuid, HttpServletRequest request) {
        //1 获取token，并解析token，拿到userid
        String token = request.getHeader("authorization");
        Claims claims = JWTUtil.parseToken(token, "admin");
        //2 解析是否成功
        if (claims==null){
            return;
        }

        //3 如果代码可以执行到此行，表明token解析成功
        //获取用户的id
        String userId = claims.get("userId").toString();
        // 4 去redis中取数据
        String info = redisTemplate.opsForValue().get(userId);
        if(info!=null&&!"".equals(info.trim())){
            //解析
            List<Cart> list = JSON.parseArray(info, Cart.class);
            Cart cart = null;
            for(Cart c:list){
                if(c.getSkuid().equals(skuid)){
                    cart =c;
                    break;
                }
            }
            if(cart!=null){
                list.remove(cart);
            }
            //将list重新放入redis
            redisTemplate.opsForValue().set(userId,JSON.toJSONString(list));
        }
    }

}
